package Singleton;

/**
 * @author Jimmy Zhan WORKSTATION
 * @since 2023/7/18 18:47
 * 说明：
 *      为了解决_04_线程安全的懒汉式中的性能低下问题，我们需要改变加锁的时机
 */

public class _05_Lazy_DoubleCheck_Static {

    private _05_Lazy_DoubleCheck_Static(){}

    // volatile 关键字保证指令的有序性
    private static volatile _05_Lazy_DoubleCheck_Static lazy;

    public static _05_Lazy_DoubleCheck_Static getInstance(){
        // 第一次判断
        if (lazy == null) {
            // 当lazy没有实例的时候，使用同步代码块上锁
            synchronized (_05_Lazy_DoubleCheck_Static.class) {  // 当前类的字节码对象
                // 第二次判断，为了防止高并发场景下，在上锁的期间其他线程创建了lazy的实例
                if (lazy == null) {
                    lazy = new _05_Lazy_DoubleCheck_Static();
                }
            }
        }
        // 如果lazy != null 就直接返回，不需要上锁
        return lazy;
    }

    // 但是这种方式在多线程高并发的情况下可能会出现空指针问题
    // 原因是JVM在实例化对象的时候会进行优化和指令重排序的操作。
    // 要解决double check带来的空指针问题，只需要使用volatile关键字即可，volatile可以保证可见性和有序性
}
